package ext.sim;

import context.environ.Keys;
import context.environ.Mouse;
import context.environ.Time;
import context.environ.Window;
import context.render.camera.Camera;
import math.math;
import math.vec2;

public class Player
{
    
    public Camera mCam;
    
    private double mVelocity;
    
    
    public Player()
    {
        this.mCam = new Camera();
    }
    
    
    public void onTick()
    {
        double timeDelta = Time.get().delta();
        
        vec2 delta = vec2.div(new vec2(Mouse.get().mDeltaPos), new vec2(Window.get().mSize.y));
        delta.mul(Mouse.get().mSensitivity / timeDelta);
        double angX = this.mCam.mAngles.x - delta.y;
        double angY = this.mCam.mAngles.y + delta.x;
        angX = math.min(angX, 0.5 * math.PI);
        angX = math.max(angX, -0.5 * math.PI);
        this.mCam.mAngles.x = angX;
        this.mCam.mAngles.y = angY;
        
        if (Keys.get().isDown(Keys.SHIFT_L))
        {
            this.mVelocity = 10;
        }
        else
        {
            this.mVelocity = 4;
        }
        
        boolean w = Keys.get().isDown(Keys.W);
        boolean s = Keys.get().isDown(Keys.S);
        boolean a = Keys.get().isDown(Keys.A);
        boolean d = Keys.get().isDown(Keys.D);
        this.move(timeDelta, w, s, a, d);
        
        double transl = timeDelta * this.mVelocity;
        boolean r = Keys.get().isDown(Keys.R);
        boolean f = Keys.get().isDown(Keys.F);
        if (!r || !f)
        {
            if (r && !f)
            {
                this.mCam.mOrig.y += transl;
            }
            else if (!r && f)
            {
                this.mCam.mOrig.y -= transl;
            }
        }
        
        this.mCam.updateFrustum();
    }
    
    
    private void move(
            double aTimeDelta, 
            boolean w, 
            boolean s, 
            boolean a, 
            boolean d)
    {
        if (!w || !s || !a || !d)
        {
            vec2 dForw = new vec2(math.sin(this.mCam.mAngles.y), -math.cos(this.mCam.mAngles.y));
            vec2 dRght = new vec2(-dForw.y, dForw.x);
            vec2 dLeft = vec2.mul(dRght, -1);
            vec2 dBack = vec2.mul(dForw, -1);
            if (w && s)
            {
                if (a)
                {
                    this.moveIn(dLeft, aTimeDelta);
                }
                else if (d)
                {
                    this.moveIn(dRght, aTimeDelta);
                }
            }
            else if (a && d)
            {
                if (w)
                {
                    this.moveIn(dForw, aTimeDelta);
                }
                else if (s)
                {
                    this.moveIn(dBack, aTimeDelta);
                }
            }
            else if (w && a)
            {
                vec2 sum = vec2.add(dForw, dLeft);
                vec2 dForwLeft = vec2.mul(sum, math.REC_RT2);
                this.moveIn(dForwLeft, aTimeDelta);
            }
            else if (a && s)
            {
                vec2 sum = vec2.add(dBack, dLeft);
                vec2 dBackLeft = vec2.mul(sum, math.REC_RT2);
                this.moveIn(dBackLeft, aTimeDelta);
            }
            else if (s && d)
            {
                vec2 sum = vec2.add(dBack, dRght);
                vec2 dBackRght = vec2.mul(sum, math.REC_RT2);
                this.moveIn(dBackRght, aTimeDelta);
            }
            else if (d && w)
            {
                vec2 sum = vec2.add(dForw, dRght);
                vec2 dForwRght = vec2.mul(sum, math.REC_RT2);
                this.moveIn(dForwRght, aTimeDelta);
            }
            else if (w)
            {
                this.moveIn(dForw, aTimeDelta);
            }
            else if (s)
            {
                this.moveIn(dBack, aTimeDelta);
            }
            else if (a)
            {
                this.moveIn(dLeft, aTimeDelta);
            }
            else if (d)
            {
                this.moveIn(dRght, aTimeDelta);
            }
        }
    }
    
    private void moveIn(vec2 aDir, double aTimeDelta)
    {
        vec2 transl = vec2.mul(aDir, aTimeDelta * this.mVelocity);
        this.mCam.mOrig.x += transl.x;
        this.mCam.mOrig.z += transl.y;
    }
    
}
